home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / video / fly8111-.000 / fly8111- / fly8 / MSDOS / pcserial.c < prev    next >
C/C++ Source or Header  |  1979-12-31  |  9KB  |  382 lines

  1. /* --------------------------------- pcserial.c ----------------------------- */
  2.  
  3. /* This is part of the flight simulator 'fly8'.
  4.  * Author: Eyal Lebedinsky (eyal@ise.canberra.edu.au).
  5. */
  6.  
  7. /* Handler for packet level exchanges (low level). It uses the serial ports
  8.  * as the communications medium. It moves packets across the wires with some
  9.  * minimal checking (magic number in header).
  10.  * Note: 'tail' is not used for now. If async send is expected then one should
  11.  * copy the packet to a NEW(pack) and add it to the tail of the outgoing list.
  12.  * At the moment the original packet MUST BE PRESERVED (it is finaly released
  13.  * by the sender [packet_send() in remote.c].
  14.  * 'incoming' holds the partialy received packet which is delivered when fully
  15.  * acquired [packet_deliver() in netport.c].
  16.  *
  17.  * 'send' should be able to return a failure.
  18.  *
  19.  * Options:
  20.  *  0 speed    [9600-115200]
  21.  *  1 parity    ['E', 'O', 'N'] for [even, odd, none]
  22.  *  2 bits    [5, 6, 7, 8]                    must be 8!
  23.  *  3 stop    [0, 1, 2] for [1, 1.5, 2]
  24.  *  4 xmode    ['i', 'o', 'b'] for [input, output, both]    do not use!
  25.  *  5 isize    [input buffer size]
  26.  *  6 osize    [output buffer size]
  27.  *  - irq    [hardware IRQ used for this serial com port]
  28.  *  - base    [hardware base address used for this serial com port]
  29. */
  30.  
  31. #include "fly.h"
  32. #include "com.h"
  33.  
  34.  
  35. #define MAGIC1    ((Uchar)0x5a)
  36. #define MAGIC2    ((Uchar)0xa5)
  37. #define    COMHDSZ    4        /* header size */
  38.  
  39. typedef struct port PORT;
  40.  
  41. struct port {
  42.     int    comport;
  43.     long    speed;
  44.     int    parity;
  45.     int    bits;
  46.     int    stop;
  47.     int    xmode;
  48.     int    isize;
  49.     int    osize;
  50.     int    irq;
  51.     int    base;
  52.     int    flags;
  53.     long    last_in;
  54.     int    panic;
  55.     PACKET    *incoming;
  56.     PACKET    *outgoing;
  57.     PACKET    *tail;
  58.     char    head[COMHDSZ];
  59.     short    netport;
  60.     Uchar    address[LADDRESS];
  61. };
  62.  
  63. static PORT    ports[] = {
  64.     {1, 115200L, 'N', 8, 1, 0, 4096, 0, -1, -1},
  65.     {2, 115200L, 'N', 8, 1, 0, 4096, 0, -1, -1},
  66.     {3, 115200L, 'N', 8, 1, 0, 4096, 0, -1, -1},
  67.     {4, 115200L, 'N', 8, 1, 0, 4096, 0, -1, -1}
  68. };
  69. #define    NPORTS    (sizeof(ports)/sizeof(ports[0]))
  70.  
  71. static int    nports = 0;        /* active com ports */
  72.  
  73. LOCAL_FUNC int NEAR
  74. SerOptions (PORT *port, char *options)
  75. {
  76.     char    *p;
  77.     long    l;
  78.  
  79.     if (!get_niarg (options, 0, &l))
  80.         port->speed = l;
  81.     if (T(p = get_iarg (options, 1)))
  82.         port->parity = *p;
  83.     if (!get_niarg (options, 2, &l))
  84.         port->bits = (int)l;
  85.     if (!get_niarg (options, 3, &l))
  86.         port->stop = (int)l;
  87.     if (T(p = get_iarg (options, 4))) {
  88.         if (*p == 'i')
  89.             port->xmode = Xin;
  90.         else if (*p == 'o')
  91.             port->xmode = Xout;
  92.         else if (*p == 'b')
  93.             port->xmode = Xin|Xout;
  94.         else if (*p == ':')
  95.             ;
  96.         else {
  97.             MsgEPrintf (-100, "%s: bad Xon option", port->address);
  98.             return (1);
  99.         }
  100.     }
  101.     if (!get_niarg (options, 5, &l))
  102.         port->isize = (int)l;
  103.     if (!get_niarg (options, 6, &l))
  104.         port->osize = (int)l;
  105.     port->irq  = (int)(get_narg (options, "irq",  &l) ? -1 : l);
  106.     port->base = (int)(get_narg (options, "base", &l) ? -1 : l);
  107.  
  108.     return (0);
  109. }
  110.  
  111. LOCAL_FUNC int FAR
  112. SerInit (NETPORT *np, char *options)    /* init a physical com port */
  113. {
  114.     int    portno;
  115.     PORT    *port;
  116.     Uchar    unit[2];
  117.  
  118.     portno = np->unit-'1';
  119.     if (portno < 0 || portno > 3) {
  120.         MsgEPrintf (-100, "%s: bad port %c",
  121.             np->NetDriver->name, np->unit);
  122.         return (1);
  123.     }
  124.     port = &ports[portno];
  125.     if (port->flags)
  126.         return (0);        /* already inited */
  127.  
  128.     memset  (port->address, 0, LADDRESS);
  129.     strncpy ((char *)port->address, np->NetDriver->name, LADDRESS);
  130.     strncat ((char *)port->address, ".", LADDRESS);
  131.     unit[0] = (Uchar)np->unit;
  132.     unit[1] = '\0';
  133.     strncat ((char *)port->address, (char *)unit, LADDRESS);
  134.  
  135.     if (SerOptions (port, options))
  136.         return (1);
  137.  
  138.     if (!nports++)
  139.         if (com_start (-1, 0L, 0, 0, 0, 0)) {
  140.             MsgEPrintf (-100, "%s: driver failed", port->address);
  141.             return (1);
  142.         }
  143.  
  144.     if (port_set (port->comport, port->isize, port->osize, port->irq,
  145.             port->base)) {
  146.         if (!--nports)
  147.             com_stop (-1);
  148.         MsgEPrintf (-100, "%s: port set failed", port->address);
  149.         return (1);
  150.     }
  151.     if (port_start (port->comport, port->speed, port->parity,
  152.             port->bits, port->stop, port->xmode)) {
  153.         if (!--nports)
  154.             com_stop (-1);
  155.         MsgEPrintf (-100, "%s: port start failed", port->address);
  156.         return (1);
  157.     }
  158.     port->flags = 1;
  159.     port->netport = np->netport;
  160.  
  161.     return (0);
  162. }
  163.  
  164. LOCAL_FUNC void FAR
  165. SerTerm (NETPORT *np)            /* term a physical port */
  166. {
  167.     PACKET    *p;
  168.     int    portno;
  169.     PORT    *port;
  170.  
  171.     portno = np->unit-'1';
  172.     if (portno < 0 || portno > 3)
  173.         return;
  174.     port = &ports[portno];
  175.     if (!port->flags)
  176.         return;
  177.  
  178.     port_stop (port->comport);
  179.     port->flags = 0;
  180.  
  181.     for (p = port->outgoing; p;)
  182.         p = packet_del (p);
  183.     port->outgoing = 0;
  184.     port->tail = 0;
  185.  
  186.     if (port->incoming) {
  187.         packet_del (port->incoming);
  188.         port->incoming = 0;
  189.     }
  190.  
  191.     if (!--nports)
  192.         com_stop (-1);
  193. }
  194.  
  195. #if 0
  196.  
  197. /* This function sends out a packet syncronously one byte at a time with
  198.  * retries.
  199. */
  200. LOCAL_FUNC int  FAR
  201. SerOut (PORT *port)
  202. {
  203.     PACKET    *pack;
  204.     int    ch;
  205.     int    to;
  206.  
  207.     to = 0;
  208.     while (pack = port->outgoing) {        /* block while sending */
  209.         if (++to > 1000) {
  210.             MsgEPrintf (10, "T/O com.%d", port->comport);
  211.             flushccb (port->comport);
  212.             port->outgoing = 0;
  213.             return (1);
  214.         }
  215.         if (pack->flags < -COMHDSZ) {
  216.             port->head[0] = MAGIC1;
  217.             port->head[1] = MAGIC2;
  218.             port->head[2] = (Uchar)0x00ff&(pack->length >>8)
  219.             port->head[3] = (Uchar)0x00ff&(pack->length);
  220.             ++pack->flags;
  221.         }
  222.         if (pack->flags < 0)
  223.             ch = port->head[COMHDSZ+pack->flags];
  224.         else
  225.             ch = pack->raw[pack->flags];
  226.         if (!comout (port->comport, ch)) {
  227.             to = 0;
  228.             if (++pack->flags == pack->length) {
  229. #if 0
  230.                 if (!(port->outgoing = packet_del (pack))
  231.                     port->tail = 0;
  232. #else
  233.                 port->outgoing = 0;
  234. #endif
  235.             }
  236.         }
  237.     }
  238.     return (0);
  239. }
  240.  
  241. #endif
  242.  
  243. LOCAL_FUNC void  NEAR
  244. SerStats (int comport, int which)
  245. {
  246.     int    c, i, info[3];
  247.  
  248.     get_ccbinfo (comport, info);
  249.     if (which) {
  250.         c = info[1];    /* output buffer size */
  251.         i = 3;
  252.     } else {
  253.         c = info[0];    /* input  buffer size */
  254.         i = 0;
  255.     }
  256.  
  257.     ++STATS_NETERRLOW[i];
  258.     if (c > (int)STATS_NETERRLOW[i+1])
  259.         STATS_NETERRLOW[i+1] += c;
  260.     STATS_NETERRLOW[i+2] += c;
  261. }
  262.  
  263. LOCAL_FUNC int FAR
  264. SerSend (NETPORT *np, PACKET *pack)
  265. {
  266.     int    portno, ret;
  267.     PORT    *port;
  268.     Uchar    header[COMHDSZ];
  269.  
  270.     if (0 == pack)
  271.         return (0);
  272.  
  273.     portno = np->unit-'1';
  274.     if (portno < 0 || portno > 3)
  275.         return (1);
  276.     port = &ports[portno];
  277.     if (!port->flags)
  278.         return (1);
  279.  
  280. #if 0
  281.     pack->flags = -COMHDSZ - 1;
  282.     pack->next = 0;
  283.     if (port->tail)
  284.         port->tail->next = pack;
  285.     else
  286.         port->outgoing = pack;
  287.     port->tail = pack;
  288.     return (SerOut (port));
  289. #else
  290.  
  291.     header[0] = MAGIC1;
  292.     header[1] = MAGIC2;
  293.     header[2] = (Uchar)(0x00ff&(pack->length >>8));
  294.     header[3] = (Uchar)(0x00ff&(pack->length));
  295.     ret = comoutb (port->comport, header, sizeof (header)) ||
  296.           comoutb (port->comport, pack->raw, pack->length);
  297.     SerStats (port->comport, 1);    /* fullest output buffers about now */
  298.     return (ret);
  299. #endif
  300. }
  301.  
  302. LOCAL_FUNC int FAR
  303. SerReceive (NETPORT *np)
  304. {
  305.     int    ch, portno, len;
  306.     PACKET    *pack;
  307.     PORT    *port;
  308.  
  309.     portno = np->unit-'1';
  310.     if (portno < 0 || portno > 3)
  311.         return (1);
  312.     port = &ports[portno];
  313.     if (!port->flags)
  314.         return (1);
  315.     SerStats (port->comport, 0);
  316.     while ((ch = comin (port->comport)) != -1) {
  317.         port->last_in = st.present;
  318.         pack = port->incoming;
  319.         if (!pack) {
  320.             if (port->panic) {    /* drop rest of packet */
  321.                 --port->panic;
  322.                 continue;
  323.             }
  324.             if (F(pack = packet_new (PAKPACKLEN, -1))) {
  325.                 port->panic = (0x00ff & ch) - 1; /* length */
  326.                 continue;
  327.             } 
  328.             port->incoming = pack;
  329.             pack->flags = (Ushort)-COMHDSZ;
  330.             pack->next = 0;
  331.         }
  332.         if ((short)pack->flags < 0) {
  333.             pack->raw[COMHDSZ+pack->flags++] = (Uchar)ch;
  334.             if (pack->flags == (Ushort)(1-COMHDSZ) &&
  335.                  pack->raw[0] != MAGIC1 ||
  336.                 pack->flags == (Ushort)(2-COMHDSZ) &&
  337.                  pack->raw[1] != MAGIC2 ||
  338.                 pack->flags == (Ushort)(4-COMHDSZ) &&
  339.                  ((len = (pack->raw[2]<<8)+pack->raw[3]) < 2 ||
  340.                   len > PAKPACKLEN)) {
  341.                 ++STATS_NETERRD;
  342.                 pack->flags = (Ushort)-COMHDSZ;    /* restart */
  343.             } else if (pack->flags == 4-COMHDSZ)
  344.                 pack->length = (short)len;
  345.             continue;
  346.         }
  347.         pack->raw[pack->flags++] = (Uchar)ch;
  348.         if (pack->flags == (Ushort)pack->length) {
  349. #if 0
  350.             pack->netport = port->netport;
  351.             pack->address = port->address;
  352.             packet_deliver (pack);
  353.             port->incoming = 0;
  354. #else
  355.             PACKET    *lpack;
  356.  
  357.             if (F(lpack = packet_new (pack->length, -1)))
  358.                 ++STATS_NETERRD;
  359.             else {
  360.                 lpack->netport = port->netport;
  361.                 lpack->length = pack->length;
  362.                 lpack->address = port->address;
  363.                 memcpy (lpack->raw, pack->raw, lpack->length);
  364.                 packet_deliver (lpack);
  365.             }
  366.             pack->flags = (Ushort)-COMHDSZ;    /* reuse packet */
  367. #endif
  368.         }
  369.     }
  370.     return (0);
  371. }
  372.  
  373. struct NetDriver NEAR NetCom = {
  374.     "COM",
  375.     0,
  376.     NULL,    /* extra */
  377.     SerInit,
  378.     SerTerm,
  379.     SerSend,
  380.     SerReceive
  381. };
  382.